package com.testthisepicstuff.android;

import java.io.IOException;


import org.mobilesynergies.android.epic.service.IncomingMessageCallback;
import org.mobilesynergies.android.epic.service.RemoteActivity;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
import android.util.Log;
import android.widget.TextView;

/**
 * 
 * @author Peter Rautek
 * This activity demonstrates the usage of the epic architecture. It extends the RemoteActivity from the Epic Applcation SDK for Android, that handles the basic interaction with the epic service.
 * The activity connects to an application node running on a different device that provides keyboard input.
 * The input is then displayed to the user.
 * 
 */

public class ActivityInputReceiver extends RemoteActivity{
	
	private static String CLASS_TAG = ActivityInputReceiver.class.getSimpleName();

	/**
	 * A TextView that will display the input from a remote device
	 */
	TextView mTextView = null;
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mTextView = (TextView) findViewById(R.id.TextViewDisplayText);
    }

   /**
    * Is called by the RemoteActivity when the application interface of the epic service is connected to this activity 
    */
	@Override
	public void initialize() {
		//the Epic service was detected on the device and is running
		//let's check the version of the Epic service that is installed on the device.
		int iVersion = -1;
		try {
			iVersion = mEpicService.getVersion();
		} catch (RemoteException e) {
			Log.d(CLASS_TAG, "RemoteException: "+e.getMessage());
			//TODO show error message to user
		}
		
		Log.d(CLASS_TAG, "Connected to service with version "+iVersion);
		//let's check if the version meets our requirements
		if(iVersion<1){
			Log.w(CLASS_TAG, "Wrong version of Epic Service installed.");
			//TODO point the user to a software upgrade screen
			finish();
		}
		
		//the required version of the Epic service is installed
		//we need an applicationKey, an applicationPassword, and an applicationManifest
		String applicationKey = "com.testthisepicstuff.android";
		String applicationPassword = "debugPassword";
		String applicationManifest = null;
		try {
			applicationManifest = importEpicManifest(R.raw.epic);
		} catch (IOException e1) {
			//the epic manifest file could not be read -> please fix it    
			e1.printStackTrace();
		}
		if(applicationManifest==null)
		{
			finish();			
		}
		
		//let's try to bind our application to the service (providing our applicationKey and our applicationPassword, as well as the epic-manifest xml-file describing the structure of our application)
		String sessionKey = null;
		try {
			sessionKey = mEpicService.bindApplication(applicationKey, applicationPassword, applicationManifest);
		} catch (RemoteException e) {
			//something went wrong communicating with the service (probably it crashed)
			Log.d(CLASS_TAG, "RemoteException: "+e.getMessage());
		}
		
		if(sessionKey==null){
			finish();
			//something went wrong: either the key, password combination was wrong or the manifest was invalid.
			//please check the log
		}
		
		//now we have a sessionKey that we can use to register application nodes
		//until here the initialize() method for distributedApplications will not vary a lot
		//from now on we come to the very specifics of this small application.
		//in this case we register one application node that acts as a subscriber and is waiting for input from a publisher
		//the applicationNodeSubscriberId needs to be declared in the epic manifest file
		String sessionToken = null;
		String applicationNodeSubscriberId = "keyinputsubscriber"; 
		try {
			sessionToken = mEpicService.getSessionToken(sessionKey, applicationNodeSubscriberId);
		} catch (RemoteException e) {
			//something went wrong communicating with the service (probably it crashed)
			Log.d(CLASS_TAG, "RemoteException: "+e.getMessage());
		}
		
		if(sessionToken==null){
			finish();
			//something went wrong: do you have permissions to register an application node as a subscriber?
			//please check the log
		}
		
		try {
			//the applicationNodePublisherId is the id of the application node that will send the messages
			String applicationNodePublisherId = "keyinputpublisher"; 
			//we register a callback that will be called every time the publisher sends new content 
			mEpicService.listenForMessages(sessionToken, mMessageCallback, applicationNodePublisherId);
		} catch (RemoteException e) {
			//something went wrong communicating with the service (probably it crashed)
			e.printStackTrace();
		}
	}
	
	
	/**
	 * This function is called when the epic service shut down unexpectedly 
	 */
	@Override
	public void onServiceFailure() {
		//the service shut down
		//you can not talk to the service anymore
		//display a error to the user and shut down your application or try to recover later		
	}
	
	/**
	 * Callback object that is registered as a subscriber with the epic service. 
	 * The handleMessage function is called whenever the publisher posts new content.
	 */
	IncomingMessageCallback mMessageCallback = new IncomingMessageCallback(){

		@Override
		public boolean handleMessage(Bundle message) throws RemoteException {
			//We receive the messages of the publisher.
			//The callback happens asynchronously. 
			//To expose the message to the user we need to communicate with the user-interface thread
			//Communicating to the UI thread is commonly done with a Handler in Android.
			Message msg = new Message();
			msg.setData(message);
			mHandleRemoteInput.sendMessage(msg);
			return true;
		}
	};
	
	Handler mHandleRemoteInput = new Handler(){
		
		@Override
		public void handleMessage(Message msg) {
			super.handleMessage(msg);
			String displayText = (String) mTextView.getText();
			String character = msg.getData().getString("character");			
			displayText += character;
			mTextView.setText(displayText);
		}
	};

	
}

